/******************************************************************************
 *  Copyright (C) Cambridge Silicon Radio Limited 2015
 *
 *  This software is provided to the customer for evaluation
 *  purposes only and, as such early feedback on performance and operation
 *  is anticipated. The software source code is subject to change and
 *  not intended for production. Use of developmental release software is
 *  at the user's own risk. This software is provided "as is," and CSR
 *  cautions users to determine for themselves the suitability of using the
 *  beta release version of this software. CSR makes no warranty or
 *  representation whatsoever of merchantability or fitness of the product
 *  for any particular purpose or use. In no event shall CSR be liable for
 *  any consequential, incidental or special damages whatsoever arising out
 *  of the use of or inability to use this software, even if the user has
 *  advised CSR of the possibility of such damages.
 *
 ******************************************************************************/
package com.csr.gaiacontrol.views;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.csr.gaiacontrol.R;
import com.csr.gaiacontrol.utils.Consts;
import com.csr.vmupgradelibrary.codes.ResumePoints;

/**
 * This fragment allows to build a dialog to display information during the VM update.
 */

public class VMUpdateDialog extends DialogFragment {

    /**
     * The listener to interact with the fragment which implements this fragment.
     */
    private IDialogUpdateListener mListener;
    /**
     * The progress bar displayed to the user to show the update evolution.
     */
    private ProgressBar mProgressBar;
    /**
     * The textView error to ask to the user to abort the update.
     */
    private TextView mTVError;
    /**
     * The textView error to ask to the user to abort the update.
     */
    private TextView mTVErrorMessage;
    /**
     * The text view to display the actual step.
     */
    private TextView mTVStep;
    /**
     * The text view to display a percentage during a process.
     */
    private TextView mTVPercentage;
    /**
     * The number of steps as defined in the corresponding enumeration.
     */
    private final int RESUME_POINTS_LENGTH = ResumePoints.values().length;

    /**
     * The factory method to create a new instance of this fragment using the provided parameters.
     *
     * @return A new instance of fragment VMUpdateDialog.
     */
    public static VMUpdateDialog newInstance(IDialogUpdateListener listener) {
        VMUpdateDialog fragment = new VMUpdateDialog();
        fragment.setListener(listener);
        return fragment;
    }

    /**
     * Constructor.
     */
    public VMUpdateDialog() {
        super();
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the Builder class for convenient dialog construction
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        // title for the dialog
        builder.setTitle(R.string.update_in_progress);
        // the central view: no other choice than "null" for the last parameter, see Android developer documentation.
        View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_update_in_progress, null);
        builder.setView(view);
        // the abort button
        builder.setNegativeButton(R.string.update_abort, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (mListener != null) {
                    mListener.abortUpdate();
                }
            }
        });
        builder.setPositiveButton("", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });
        // the user can not dismiss the dialog using the back button.
        setCancelable(false);

        init(view);

        return builder.create();
    }

    /**
     * To display a percentage number during the Step DATA_TRANSFER.
     *
     * @param percentage
     *                  The percentage to display, between 0 and 100.
     */
    public void displayPercentage(int percentage) {
        if (this.isAdded() || this.isVisible()) {
            if (percentage < 0) {
                percentage = 0;
            }
            else if (percentage > 100) {
                percentage = 100;
            }
            mTVPercentage.setText(" " + percentage + Consts.PERCENTAGE_CHARACTER);
        }
    }

    /**
     * To display an error message.
     */
    public void showError(String error) {
        mTVError.setVisibility(View.VISIBLE);
        mTVErrorMessage.setVisibility(View.VISIBLE);
        mTVErrorMessage.setText(error);
    }

    /**
     * To hide the error message.
     */
    public void hideError() {
        mTVError.setVisibility(View.GONE);
        mTVErrorMessage.setVisibility(View.GONE);
    }

    /**
     * To update the view depending on the actual step.
     */
    public void updateStep() {
        mTVStep.setText(getStepLabel());

        if (mListener.getResumePoint() == ResumePoints.DATA_TRANSFER) {
            mTVPercentage.setVisibility(View.VISIBLE);
        }
        else {
            mTVPercentage.setVisibility(View.GONE);
        }
        updateProgress();
    }

    /**
     * To change the state of the progress bar as indeterminate
     *
     * @param indeterminate
     */
    public void setProgressIndeterminate(boolean indeterminate) {
        mProgressBar.setIndeterminate(indeterminate);
    }

    /**
     * To define the progress for the status bar.
     */
    private void updateProgress() {
        ResumePoints point = mListener.getResumePoint();
        int stepProgress = 0;
        if (point != null) {
            stepProgress = (point.ordinal() + 1) * 100 / RESUME_POINTS_LENGTH;
        }
        mProgressBar.setProgress(stepProgress);
    }

    /**
     * This method allows to initialize components.
     *
     * @param view
     *            The inflated view for this fragment.
     */
    private void init(View view) {
        mProgressBar = (ProgressBar) view.findViewById(R.id.pb_update);
        mTVError = (TextView) view.findViewById(R.id.tv_update_error);
        mTVErrorMessage = (TextView) view.findViewById(R.id.tv_update_error_message);
        mTVStep = (TextView) view.findViewById(R.id.tv_step);
        mTVPercentage = (TextView) view.findViewById(R.id.tv_percentage);
        updateStep();
    }

    /**
     * To get the label for the step to display it.
     * 
     * @return The label which corresponds to the actual step.
     */
    private String getStepLabel() {
        if (mListener.getResumePoint() == null) {
            return getResources().getString(R.string.update_step_initialisation);
        }
        switch (mListener.getResumePoint()) {
        case DATA_TRANSFER:
            return getResources().getString(R.string.update_step_data_transfer);
        case VALIDATION:
            return getResources().getString(R.string.update_step_validation);
        case TRANSFER_COMPLETE:
            return getResources().getString(R.string.update_step_transfer_complete);
        case IN_PROGRESS:
            return getResources().getString(R.string.update_step_in_progress);
        case COMMIT:
            return getResources().getString(R.string.update_step_commit);
        default:
            return getResources().getString(R.string.update_step_initialisation);
        }
    }

    /**
     * To define the listener for actions on this dialog. We can't use the onAttach method to define a listener: here
     * the listener is a fragment.
     *
     * @param listener
     *            The listener which will listen this dialog.
     */
    private void setListener(IDialogUpdateListener listener) {
        this.mListener = listener;
    }

    /**
     * This interface allows this Dialog fragment to communicate with its listener.
     */
    public interface IDialogUpdateListener {
        /**
         * To abort the update.
         */
        public void abortUpdate();


        /**
         * To know the step for the dialog to display.
         *
         * @return
         *          The actual resume point to display the step into the dialog.
         */
        public ResumePoints getResumePoint();
    }
}
